﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using log4net;

namespace Tireguit.Nmon.Parser.Database
{
    public class DatabaseManager:IDisposable
    {
        protected bool disposed=false;
        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    if (_dictionary!=null)
                    {
                        _dictionary.Dispose();
                        _dictionary = null;

                    }
                }
                disposed = true;
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        ~DatabaseManager()
        {
            Dispose(false);
        }

        protected ILog _log = LogManager.GetLogger(typeof(DatabaseManager));
        public IDbConnection Connection { get; protected set; }
        public DateTime DatetimeFile { get; protected set; }
        protected bool _firsttime = true;
        protected Dict.NmonElementsDictionnary _dictionary = new Dict.NmonElementsDictionnary();
        public DatabaseManager(IDbConnection connection)
        {
            Connection = connection;

        }
        public bool Open()
        {
            try
            {
                _log.Debug("start Open");
                if (Connection.State!=ConnectionState.Open)
                {
                    Connection.Open();
                }
                return true;
            }
            catch (System.Exception ex)
            {
                _log.Error("Open", ex);
                return false;
            }
            finally
            {
                _log.Debug("stop Open");
            }
        }
        public void Close()
        {
            try
            {
                _log.Debug("start Close");
                if (Connection.State != ConnectionState.Closed)
                {
                    Connection.Close();
                }
            }
            catch (System.Exception ex)
            {
                _log.Error("Close", ex);
            }
            finally
            {
                _log.Debug("stop Close");
            }
        }
        public virtual bool CleanDatabase()
        {
            bool connectionopened = false;
            IDbTransaction transaction = null;

            try
            {
                _log.Debug("start CleanDatabase");
                if (Connection.State != ConnectionState.Open)
                {
                    Connection.Open();
                    connectionopened = true;
                }
                List<IDbCommand> listcde = NmonTables.TablesDictionnary.GetTruncateCommand(Connection);
                if (listcde == null)
                {
                    return false;
                }
                transaction = Connection.BeginTransaction();
                foreach (IDbCommand command in listcde)
                {
                    command.Transaction = transaction;
                    command.ExecuteNonQuery();
                }
                transaction.Commit();
                transaction.Dispose();
                transaction = null;
                return true;
            }
            catch (System.Exception ex)
            {
                _log.Error("CleanDatabase", ex);
                return false;
            }
            finally
            {
                try
                {
                    try
                    {
                        if (transaction != null)
                        {
                            transaction.Rollback();
                            transaction.Dispose();
                        }
                    }
                    catch (System.Exception)
                    {
                    	
                    }
                    
                    if (connectionopened)
                    {
                        if (Connection.State != ConnectionState.Closed)
                            Connection.Close();
                    }

                }
                catch (System.Exception)
                {

                }
                _log.Debug("stop CleanDatabase");
            }
        }
        public virtual bool InsertInto(string line)
        {
            IDbTransaction transaction = null;
            bool connectionopened = false;
            try
            {
                _log.Debug("start InsertInto");
                if (Connection.State != ConnectionState.Open)
                {
                    Connection.Open();
                    connectionopened = true;
                }
                transaction = Connection.BeginTransaction();
                BaliseType balise = Common.NmonElement.GetBaliseElement(line);
                if (balise==BaliseType.UKNOWN)
                {
                    _log.Warn("Unknown Balise of: " + line);
                    return false;
                }
                if (!_dictionary.ContainsKey(balise))
                {
                    INmonElement element = Common.NmonElement.Create(balise,Connection);
                    if (element==null)
                    {
                        throw new ArgumentNullException("NmonElement must not be null");
                    }
                    _dictionary.Add(balise,element);
                }

                if (_firsttime&&(balise == BaliseType.ZZZZ))
                {
                    ((Statisitic.ZZZZElement)_dictionary[balise]).DatetimeFile = DatetimeFile;
                    _firsttime = false;
                }
                if (_dictionary[balise].Parse(line))
                {
                    if (balise==BaliseType.AAA)
                    {
                        DatetimeFile = ((Information.AAAElement)_dictionary[balise]).DateTimeFile;
                    }

                    List<IDbCommand> listcde = _dictionary[balise].GetInsertReq();
                    if (listcde==null)
                    {
                        return false;
                    }
                    foreach (IDbCommand command in listcde)
                    {
                        command.Transaction = transaction;
                        command.ExecuteNonQuery();
                    }
                   
                    
                    transaction.Commit();
                    transaction.Dispose();
                    transaction = null;
                    return true;
                }
                return false;

            }
            catch (System.Exception ex)
            {
                _log.Error("InsertInto", ex);
                return false;
            }
            finally
            {
                try
                {
                    if (transaction != null)
                    {
                        transaction.Dispose();
                    }
                    if (connectionopened)
                    {
                        if (Connection.State != ConnectionState.Closed)
                            Connection.Close();
                    }

                }
                catch (System.Exception)
                {

                }
                _log.Debug("stop InsertInto");
            }
        }
    }
}
